/*
 * *****************************************************************************
 *  Copyright ( c ) 2019 huibur Inc. All Rights Reserved.
 *
 *  This software is the confidential and proprietary information of Huibur Inc
 *  (*Confidential Information*). You shall not disclose such Confidential Information
 *  and shall use it only in accordance with the terms of the license agreement
 *  you entered into with Huibur or a Huibur authorized
 *  reseller (the "License Agreement*).
 *  ******************************************************************************
 */

package com.huibur.devicecheck.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.huibur.devicecheck.enums.TaskEnums;
import com.huibur.devicecheck.enums.TaskStatusEnums;
import com.huibur.devicecheck.exception.*;
import com.huibur.devicecheck.mapper.TaskMapper;
import com.huibur.devicecheck.model.param.TaskParam;
import com.huibur.devicecheck.model.po.TaskPO;
import com.huibur.devicecheck.model.query.TaskQuery;
import com.huibur.devicecheck.model.vo.TaskVO;
import com.huibur.devicecheck.request.ObjRes;
import com.huibur.devicecheck.request.PageRes;
import com.huibur.devicecheck.request.SessionContext;
import com.huibur.devicecheck.service.ITaskService;
import com.huibur.devicecheck.utils.ConvertPageUtil;
import com.huibur.devicecheck.utils.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/*******************************************************
* Title: TaskServiceImpl.java
* Description:
* @author baiqingshuo
* @date 2021/9/24
* @version 1.0
*******************************************************/
@Service
public class TaskServiceImpl extends ServiceImpl<TaskMapper, TaskPO> implements ITaskService {

    @Autowired
    TaskMapper taskMapper;

    /**
     * 新增任务
     * @param taskParam
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ObjRes<Void> insert(TaskParam taskParam) {
        TaskPO taskPO = taskMapper.selectOne(new LambdaQueryWrapper<TaskPO>()
                .eq(TaskPO::getTitle, taskParam.getTitle())
                .ne(TaskPO::getIsDeleted, TaskEnums.DELETE.getCode()));
        if (null != taskPO) {
            throw new TaskTitleRepeatException();
        }

        long planStartTime = taskParam.getPlanStartTime().getTime();
        long planEndTime = taskParam.getPlanEndTime().getTime();

        if (planEndTime <= planStartTime) {
            throw new PlanEndTimeUnableLessThanPlanStartTimeException();
        }


        TaskPO task = new TaskPO();
        task.setTitle(taskParam.getTitle());
        task.setDescription(taskParam.getDescription());
        task.setPlanStartTime(taskParam.getPlanStartTime());
        task.setPlanEndTime(taskParam.getPlanEndTime());
        task.setIsDeleted(TaskEnums.NORMAL.getCode());
        task.setCreateAt(DateUtils.getCurrentTimestamp());
        task.setCreateBy(SessionContext.getCurrentUserSubject().getUserId());
        task.setStatus(TaskStatusEnums.NOT_STARTED.getCode());
        taskMapper.insert(task);
        return new ObjRes<Void>().success("创建成功");
    }

    /**
     * 删除任务
     * @param id
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ObjRes<Void> deleteById(Long id) {
        TaskPO task = taskMapper.selectOne(new LambdaQueryWrapper<TaskPO>()
                .eq(TaskPO::getId, id));
        if (!task.getStatus().equals(TaskStatusEnums.NOT_STARTED.getCode())) {
            throw new TaskIsNotProgressException();
        }
        TaskPO taskPO = new TaskPO();
        taskPO.setId(id);
        taskPO.setIsDeleted(TaskEnums.DELETE.getCode());
        taskMapper.updateById(taskPO);
        return new ObjRes<Void>().success("删除成功");
    }

    /**
     * 编辑任务
     * @param id
     * @param taskParam
     * @return
     */
    @Override
    public ObjRes<Void> updateTask(Long id, TaskParam taskParam) {
        TaskPO task = taskMapper.selectOne(new LambdaQueryWrapper<TaskPO>()
                .ne(TaskPO::getId, id)
                .eq(TaskPO::getTitle, taskParam.getTitle())
                .ne(TaskPO::getIsDeleted, TaskEnums.DELETE.getCode()));
        if (null != task) {
            throw new TaskTitleRepeatException();
        }

        long actStartTime = taskParam.getActStartTime().getTime();
        long actEndTime = taskParam.getActEndTime().getTime();

        if (actEndTime <= actStartTime) {
            throw new ActEndTimeUnableLessThanActStartTimeException();
        }

        TaskPO taskPO = new TaskPO();
        taskPO.setTitle(taskParam.getTitle());
        taskPO.setDescription(taskParam.getDescription());
        taskPO.setPlanStartTime(taskParam.getPlanStartTime());
        taskPO.setPlanEndTime(taskParam.getPlanEndTime());
        taskPO.setActStartTime(taskParam.getActStartTime());
        taskPO.setActEndTime(taskParam.getActEndTime());
        taskPO.setIsDeleted(TaskEnums.NORMAL.getCode());
        taskPO.setUpdateAt(DateUtils.getCurrentTimestamp());
        taskPO.setUpdateBy(SessionContext.getCurrentUserSubject().getUserId());
        taskMapper.update(taskPO,new LambdaQueryWrapper<TaskPO>()
                .eq(TaskPO::getId,id));
        return new ObjRes<Void>().success("修改成功");
    }

    /**
     * 任务列表(查询并分页)
     * @param taskQuery
     * @return
     */
    @Override
    public PageRes<TaskVO> selectTaskList(TaskQuery taskQuery) {
        Page<TaskPO> page = new Page<>(taskQuery.getCurrent(), taskQuery.getPageSize());
        IPage<TaskVO> pages = taskMapper.selectTaskList(page,taskQuery);
        return ConvertPageUtil.convertPage(taskQuery.getCurrent(),page.getTotal(),pages.getRecords());

    }

    /**
     * 获取任务详情
     * @param id
     * @return
     */
    @Override
    public TaskVO selectTaskById(Long id) {
        TaskPO taskPO = taskMapper.selectOne(new LambdaQueryWrapper<TaskPO>()
                .eq(TaskPO::getId, id));
        TaskVO taskVO = new TaskVO();
        taskVO.setId(taskPO.getId());
        taskVO.setTitle(taskPO.getTitle());
        taskVO.setDescription(taskPO.getDescription());
        taskVO.setPlanStartTime(taskPO.getPlanStartTime());
        taskVO.setPlanEndTime(taskPO.getPlanEndTime());
        taskVO.setActStartTime(taskPO.getActStartTime());
        taskVO.setActEndTime(taskPO.getActEndTime());
        taskVO.setIsDeleted(taskPO.getIsDeleted());
        taskVO.setCreateAt(taskPO.getCreateAt());
        return taskVO;
    }

    /**
     * 实际开始时间
     * @return
     */
    @Override
    public ObjRes<Void> startTime(Long id) {
        TaskPO task = taskMapper.selectOne(new LambdaQueryWrapper<TaskPO>()
                .eq(TaskPO::getId, id)
                .eq(TaskPO::getIsDeleted, TaskEnums.NORMAL.getCode()));
        if (null != task.getActStartTime()) {
            throw new TaskIsStartException();
        }
        TaskPO taskPO = new TaskPO();
        taskPO.setId(id);
        taskPO.setActStartTime(DateUtils.getCurrentTimestamp());
        taskPO.setStatus(TaskStatusEnums.IN_PROGRESS.getCode());
        taskMapper.updateById(taskPO);
        return new ObjRes<Void>().success("开始成功");
    }

    /**
     * 实际结束时间
     * @param id
     * @return
     */
    @Override
    public ObjRes<Void> endTime(Long id) {
        TaskPO task = taskMapper.selectOne(new LambdaQueryWrapper<TaskPO>()
                .eq(TaskPO::getId, id)
                .eq(TaskPO::getIsDeleted, TaskEnums.NORMAL.getCode()));
        if (null != task.getActEndTime()) {
            throw new TaskHasEndedException();
        }
        TaskPO taskPO = new TaskPO();
        taskPO.setId(id);
        taskPO.setActEndTime(DateUtils.getCurrentTimestamp());
        taskPO.setStatus(TaskStatusEnums.HAS_ENDED.getCode());
        taskMapper.updateById(taskPO);
        return new ObjRes<Void>().success("结束成功");
    }
}
